{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "authorship_tag": "ABX9TyNAKuynuMdftu6lcT9ZsX4H",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/pietrolira/PPGEEC2318-Redes-Neurais-e-Deep-Learning/blob/main/Lista02/Q4.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Questão 4"
      ],
      "metadata": {
        "id": "7HkagVw_zm9T"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "**a-)** Utilizando uma rede NARX no caso uma rede neural perceptron de múltiplas camadas\n",
        "com realimentação global para fazer a predição de um passo, isto é $\\hat{x}(n+1)$, da série temporal.\n",
        "\n",
        "**Resposta:**\n",
        "Utilizando uma rede NARX (rede neural perceptron de múltiplas camadas com realimentação global), foi feita a predição de um passo da série temporal $\\hat{x}(n+1)$. A rede foi treinada com os dados da série $x(n)$ gerados pela equação:\n",
        "\n",
        "$\n",
        "x(n) = v(n) + \\beta v(n-1)v(n-2), \\quad \\beta = 0{,}5\n",
        "$\n",
        "\n",
        "com $v(n) \\sim \\mathcal{N}(0, 1)$."
      ],
      "metadata": {
        "id": "qb0uN2IW0o-D"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "**b-)** Repetir o problema utilizando uma rede LSTM.\n",
        "Avalie o desempenho das redes recorrentes mostrando a curva da série temporal, a curva\n",
        "de predição e a curva do erro de predição $e(n+1) = x(n+1) - \\hat{x}(n+1)$.\n",
        "\n",
        "**Resposta:**\n",
        "O mesmo problema foi repetido utilizando uma rede LSTM e as curvas obtidas foram:\n",
        "\n",
        "* **Curva da série temporal:** sequência real de $x(n)$.\n",
        "* **Curva de predição:** saída da rede $\\hat{x}(n+1)$.\n",
        "* **Curva do erro de predição:** $e(n+1) = x(n+1) - \\hat{x}(n+1)$."
      ],
      "metadata": {
        "id": "yHj4NE_-5ChA"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "---"
      ],
      "metadata": {
        "id": "eVMgJHtU5e6r"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "Gerar a série temporal x(n)"
      ],
      "metadata": {
        "id": "_YTSLmgb5JFL"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "x(n)=v(n)+βv(n−1)v(n−2)\n",
        "com\n",
        "𝛽\n",
        "=\n",
        "0.5\n",
        "β=0.5, onde\n",
        "𝑣\n",
        "(\n",
        "𝑛\n",
        ")\n",
        "v(n) é ruído branco gaussiano (média 0, variância 1)."
      ],
      "metadata": {
        "id": "kSiQIzd_5khq"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import numpy as np\n",
        "N = 1000\n",
        "beta = 0.5\n",
        "np.random.seed(42)\n",
        "v = np.random.randn(N)\n",
        "x = np.zeros(N)\n",
        "for n in range(2, N):\n",
        "    x[n] = v[n] + beta * v[n-1] * v[n-2]"
      ],
      "metadata": {
        "id": "-POiV-Vs5rGV"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Preparar os dados\n",
        "\n",
        "a) Para NARX:\n",
        "Usamos os valores passados como entradas:\n",
        "𝑥\n",
        "(\n",
        "𝑛\n",
        "−\n",
        "1\n",
        ")\n",
        ",\n",
        "𝑥\n",
        "(\n",
        "𝑛\n",
        "−\n",
        "2\n",
        ")\n",
        "x(n−1),x(n−2) → prever\n",
        "𝑥\n",
        "(\n",
        "𝑛\n",
        "+\n",
        "1\n",
        ")\n",
        "x(n+1)."
      ],
      "metadata": {
        "id": "qWw9bEoG5ugC"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "def preparar_dados_narx(x, atrasos=2):\n",
        "    X, Y = [], []\n",
        "    for i in range(atrasos, len(x)-1):\n",
        "        X.append([x[i-1], x[i-2]])\n",
        "        Y.append(x[i+1])\n",
        "    return np.array(X), np.array(Y)"
      ],
      "metadata": {
        "id": "keUAzAWV53rY"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "b) Para LSTM:\n",
        "Mesmo conjunto, mas com shape 3D: [samples, timesteps, features]."
      ],
      "metadata": {
        "id": "4fUWvd7g56AT"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "def preparar_dados_lstm(x, atrasos=2):\n",
        "    X, Y = [], []\n",
        "    for i in range(atrasos, len(x)-1):\n",
        "        X.append([[x[i-2]], [x[i-1]]])\n",
        "        Y.append(x[i+1])\n",
        "    return np.array(X), np.array(Y)"
      ],
      "metadata": {
        "id": "rzHqPC_k571z"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Dividir treino/teste e normalizar os dados\n",
        "python\n",
        "Copiar\n",
        "Editar\n"
      ],
      "metadata": {
        "id": "FdsJTpOe5_CE"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from sklearn.model_selection import train_test_split\n",
        "from sklearn.preprocessing import MinMaxScaler\n",
        "\n",
        "# Preparar os dados\n",
        "X_narx, y_narx = preparar_dados_narx(x)\n",
        "X_lstm, y_lstm = preparar_dados_lstm(x)\n",
        "\n",
        "# Divisão\n",
        "X_train_narx, X_test_narx, y_train_narx, y_test_narx = train_test_split(X_narx, y_narx, test_size=0.2, shuffle=False)\n",
        "X_train_lstm, X_test_lstm, y_train_lstm, y_test_lstm = train_test_split(X_lstm, y_lstm, test_size=0.2, shuffle=False)\n",
        "\n",
        "# Normalização\n",
        "scaler = MinMaxScaler()\n",
        "X_train_narx = scaler.fit_transform(X_train_narx)\n",
        "X_test_narx = scaler.transform(X_test_narx)\n",
        "\n",
        "X_train_lstm = scaler.fit_transform(X_train_lstm.reshape(-1, 2)).reshape(-1, 2, 1)\n",
        "X_test_lstm = scaler.transform(X_test_lstm.reshape(-1, 2)).reshape(-1, 2, 1)"
      ],
      "metadata": {
        "id": "eqJaGDd06B6L"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Treinar e testar os modelos\n",
        "\n",
        "a) NARX (simulada com MLP)"
      ],
      "metadata": {
        "id": "S3WmERjm6D97"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "LSTM\n",
        "python\n",
        "Copiar\n",
        "Editar\n"
      ],
      "metadata": {
        "id": "vx86RS_16ILk"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from tensorflow.keras.layers import LSTM\n",
        "\n",
        "model_lstm = Sequential([\n",
        "    LSTM(10, input_shape=(2, 1)),\n",
        "    Dense(1)\n",
        "])\n",
        "model_lstm.compile(optimizer=Adam(learning_rate=0.01), loss='mse')\n",
        "model_lstm.fit(X_train_lstm, y_train_lstm, epochs=50)"
      ],
      "metadata": {
        "id": "KDRUm2Ea6Lxc"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Avaliação e gráfico\n",
        "python\n",
        "Copiar\n",
        "Editar"
      ],
      "metadata": {
        "id": "E8RoKZJQ6Nrj"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "# Predição\n",
        "y_pred_narx = model_narx.predict(X_test_narx).flatten()\n",
        "y_pred_lstm = model_lstm.predict(X_test_lstm).flatten()\n",
        "\n",
        "erro_narx = y_test_narx - y_pred_narx\n",
        "erro_lstm = y_test_lstm - y_pred_lstm\n",
        "\n",
        "# Plot\n",
        "plt.figure(figsize=(14, 10))\n",
        "plt.subplot(3, 1, 1)\n",
        "plt.plot(y_test_narx, label='Real')\n",
        "plt.plot(y_pred_narx, label='Predição NARX')\n",
        "plt.title('Predição da Série Temporal - Rede NARX')\n",
        "plt.legend()\n",
        "\n",
        "plt.subplot(3, 1, 2)\n",
        "plt.plot(y_test_lstm, label='Real')\n",
        "plt.plot(y_pred_lstm, label='Predição LSTM')\n",
        "plt.title('Predição da Série Temporal - Rede LSTM')\n",
        "plt.legend()\n",
        "\n",
        "plt.subplot(3, 1, 3)\n",
        "plt.plot(erro_narx, label='Erro NARX')\n",
        "plt.plot(erro_lstm, label='Erro LSTM')\n",
        "plt.title('Erro de Predição')\n",
        "plt.legend()\n",
        "\n",
        "plt.tight_layout()\n",
        "plt.show()"
      ],
      "metadata": {
        "id": "JrkMLDih6PxL"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}